﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Windy.Json 
{
    public static class JsonWriterExtension
    {
        public static string ToJsonText(this JsonNotation notation)
        {
            switch (notation.Type)
            {
                case JsonNotationType.True:
                    return "true";
                case JsonNotationType.False:
                    return "false";
                case JsonNotationType.Null:
                    return "null";
                case JsonNotationType.ObjectBegin:
                    return "{";
                case JsonNotationType.ObjectEnd:
                    return "}";
                case JsonNotationType.ArrayBegin:
                    return "[";
                case JsonNotationType.ArrayEnd:
                    return "]";
                case JsonNotationType.NameSeperator:
                    return ":";
                case JsonNotationType.MemberSeperator:
                    return ",";
                case JsonNotationType.String:
                    return string.Format("\"{0}\"", JsonStringEscaped(notation.Value));
                case JsonNotationType.Number:
                    return notation.Value.ToString(System.Globalization.NumberFormatInfo.InvariantInfo);
                case JsonNotationType.Undefined:
                    return JsonStringEscaped(notation.Value);
                default:
                    System.Diagnostics.Debug.Fail("Unexpected JsonNotationType", notation.Type.ToString());
                    return notation.Value.ToString();
            }
        }

        public static string ToJsonText(this IEnumerable<JsonNotation> notations)
        {
            StringBuilder buffer = new StringBuilder();
            notations.WriteTo(buffer);
            return buffer.ToString();
        }

        public static string JsonStringEscaped(this string original)
        {
            StringBuilder buffer = new StringBuilder(original.Length);
            foreach (var fo in original)
            {
                switch (fo)
                {
                    case '\'':
                        buffer.Append(@"\'");
                        break;
                    case '"':
                        buffer.Append("\\\"");
                        break;
                    case '\\':
                        buffer.Append(@"\\");
                        break;
                    case '/':
                        buffer.Append(@"\/");
                        break;
                    case '\b':
                        buffer.Append(@"\b");
                        break;
                    case '\f':
                        buffer.Append(@"\f");
                        break;
                    case '\n':
                        buffer.Append(@"\n");
                        break;
                    case '\r':
                        buffer.Append(@"\r");
                        break;
                    case '\t':
                        buffer.Append(@"\t");
                        break;
                    default:
                        buffer.Append(fo);
                        break;
                }
            }

            return buffer.ToString();
        }

        public static void WriteTo(this IEnumerable<JsonNotation> notations, StringBuilder buffer)
        {
            StringWriter writer = new StringWriter(buffer);

            notations.WriteTo(writer);
        }

        public static void WriteTo(this IEnumerable<JsonNotation> notations, Stream stream)
        {
            StreamWriter writer = new StreamWriter(stream);
            notations.WriteTo(writer);
        }

        public static void WriteTo(this IEnumerable<JsonNotation> notations, TextWriter writer)
        {
            foreach (var fo in notations)
            {
                writer.Write(fo.ToJsonText());
            }
        }

        public static void Append(this StringBuilder buffer, IEnumerable<JsonNotation> notations)
        {
            notations.WriteTo(buffer);
        }

        public static void Write(this Stream stream, IEnumerable<JsonNotation> notations)
        {
            notations.WriteTo(stream);
        }

        public static void Write(this TextWriter writer, IEnumerable<JsonNotation> notations)
        {
            notations.WriteTo(writer);
        }
    }
}
